#include "wtlpch.h"

#include "resource.h"
#include "MainDownListView.h"
#include "DownPropertyDiag.h"

#define DOWNLOADLIST_COLUMN_MAX_CHAR	32

#define STATUS_COLUMN_INIT_WIDTH		25
#define FILENAME_COLUMN_INIT_WIDTH		500
#define FILESIZE_COLUMN_INIT_WIDTH		100
#define MAX_DOWNFILE_INFO_BUFFER		512
#define MAX_DOWNFILE_FORMAT_BUFFER		128

#define DLST_DOWNSTATUS_COL_INDEX		0
#define DLST_FILENAME_COL_INDEX			1
#define DLST_FILESIZE_COL_INDEX			2
#define DLST_FINISHEDSIZE_COL_INDEX		3
#define DLST_FINISHEDPERCENT_COL_INDEX	4
#define DLST_TIMELEFT_COL_INDEX			5
#define DLST_SPEED_COL_INDEX			6

#define DOWNLIST_PROGRESS_COLOR			RGB(0x11,0x92,0x33)

CMainDownListView::CMainDownListView() : m_pDownInfoListView(NULL), m_nMaxParallelDownLoad(1)
{
	//Prepare the status bitmap
	m_bmpSchedule.LoadBitmapW(IDB_BM_SCHEDULE);
	m_bmpSniffering.LoadBitmapW(IDB_BM_SNIFFERING);
	m_bmpReady.LoadBitmapW(IDB_BM_TASKWAIT);
	m_bmpDonwloading.LoadBitmapW(IDB_BM_DOWNLOADING);
	m_bmpFinished.LoadBitmapW(IDB_BM_TASKFINISH);
	m_bmpPaused.LoadBitmapW(IDB_BM_PAUSE);

	//Also we need alpha blend
	alphaBlendFunction.BlendOp = AC_SRC_OVER;
	alphaBlendFunction.BlendFlags = 0;
	alphaBlendFunction.AlphaFormat = AC_SRC_ALPHA;
	alphaBlendFunction.SourceConstantAlpha = 255;	//Our bitmap is 32bit with alpha chanel
}

CMainDownListView::~CMainDownListView()
{
	//Destory ImageList
	m_imglstDummy.Destroy();

	//Clear member heap
	ClearPageLinkHeap();
}

LRESULT CMainDownListView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	//Set Exstyle
	SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	//Create a dummy Imagelist for colum resize
	m_imglstDummy.Create(18, 18, ILC_COLOR32 | ILC_MASK, 1, 0);
	SetImageList(m_imglstDummy, LVSIL_SMALL);

	//Load Context Menu
	m_contMenu.LoadMenuW(IDR_DOWNLIST_CONTEXT);

	//Add Toolbar for UI Handling
	UIAddToolBar(m_tbDownToolbar.m_hWnd);

	bHandled = FALSE;
	return FALSE;
}

LRESULT CMainDownListView::OnSnifferLink(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	//Convert the params, the item index is base on listall
	DOWN_LIST_ITEM* pItem = (DOWN_LIST_ITEM*)wParam;
	CCURLHelper::PAGE_LINK_ITEM::LINK_STATUS stStatus = (CCURLHelper::PAGE_LINK_ITEM::LINK_STATUS)lParam;

	//Prepare the buffer
	WCHAR pwstrInfoFormat[MAX_DOWNFILE_FORMAT_BUFFER] = { 0 };
	WCHAR pwstrInfoText[MAX_DOWNFILE_INFO_BUFFER] = { 0 };
	WCHAR pwstrInfoUNICODE[MAX_DOWNFILE_INFO_BUFFER] = { 0 };

	switch(stStatus)
	{
	case CCURLHelper::PAGE_LINK_ITEM::ST_STARTITEM:

		//Load Format string from resource and set the output
		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_START_ITEM, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		::wsprintfW(pwstrInfoText, pwstrInfoFormat, pItem->wstrFileName.c_str());
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoText);

		//Change Item Status
		pItem->itemType = DOWNLIST_SNIFFERING;

		//Refresh List Item Status
		SetFocus();
		SelectItem(pItem->uiItemIndex);
		Update(pItem->uiItemIndex);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_BEGIN_CONNECT:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_BEGIN_CONNECT, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);

		//We have to convert page link url to UNICODE
		::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_vecPageLinkItem[pItem->uiItemIndex]->strLinkPage.c_str(), -1, pwstrInfoUNICODE, MAX_DOWNFILE_INFO_BUFFER);
		::wsprintfW(pwstrInfoText, pwstrInfoFormat, pwstrInfoUNICODE);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoText);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTP_OK:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTP_OK, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTP_GZIP:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTP_GZIP, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTP_GZDECOK:
		
		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTP_GZDECOK, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTP_GZDECFAIL:
		
		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTP_GZDECFAIL, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_ERROR, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTP_PLAIN:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTP_PLAIN, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_NEED_CAPTCHA:
		
		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_NEED_CAPTCHA, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_REC_CAPTCHA:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_REC_CAPTCHA, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);

		::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_vecPageLinkItem[pItem->uiItemIndex]->strCaptcha.c_str(), -1, pwstrInfoUNICODE, MAX_DOWNFILE_INFO_BUFFER);
		::wsprintfW(pwstrInfoText, pwstrInfoFormat, pwstrInfoUNICODE);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoText);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_GETLINKOK:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_GETLINK_OK, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		::wsprintfW(pwstrInfoText, pwstrInfoFormat, m_vecPageLinkItem[pItem->uiItemIndex]->wstrServerFileName.c_str());
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_OK, pwstrInfoText);

		//Change status and update info
		pItem->itemType = DOWNLIST_READY;
		pItem->strDownLink = m_vecPageLinkItem[pItem->uiItemIndex]->strDownLink;
		pItem->strFileLink = m_vecPageLinkItem[pItem->uiItemIndex]->strFileLink;
		pItem->wstrServerFileName = m_vecPageLinkItem[pItem->uiItemIndex]->wstrServerFileName;
		
		//Update the downlist view
		Update(pItem->uiItemIndex);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_GETLINKFAIL:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_GETLINK_FAIL, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_ERROR, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_HTTPFAIL:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_HTTPFAIL, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_ERROR, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_TIMEOUT:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_TIMEOUT, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_ERROR, pwstrInfoFormat);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_WAITFORNEXT:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_WAITFORNEXT, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		::wsprintfW(pwstrInfoText, pwstrInfoFormat, _ConfigApp.AppSettings.uiJSItemSnifferTimeWait);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_INFO, pwstrInfoText);
		break;

	case CCURLHelper::PAGE_LINK_ITEM::ST_FINISH:

		::LoadStringW(_Module.m_hInst, IDS_TA_DOWNINFO_FINISH, pwstrInfoFormat, MAX_DOWNFILE_FORMAT_BUFFER);
		m_pDownInfoListView->ShowInfo(CFileDownInfoList::ST_OTHER, pwstrInfoFormat);

		//Prompt for download
		ShowDownProperty();

		break;
	}

	return FALSE;
}

LRESULT CMainDownListView::OnDownloadingStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	//Convert the params, the item index is base on listall
	DOWN_LIST_ITEM* pItem = (DOWN_LIST_ITEM*)wParam;
	CCURLHelper::DOWN_FILE_DESCRIPTOR::DOWNLOADING_STATUS stStatus = (CCURLHelper::DOWN_FILE_DESCRIPTOR::DOWNLOADING_STATUS)lParam;

	switch(stStatus)
	{
	case CCURLHelper::DOWN_FILE_DESCRIPTOR::ST_BEGINDOWNLOAD:

		//Change status
		pItem->itemType = DOWNLIST_DOWNLOADING;

		//Refresh List Item Status
		SetFocus();
		SelectItem(pItem->uiItemIndex);
		Update(pItem->uiItemIndex);
		break;

	case CCURLHelper::DOWN_FILE_DESCRIPTOR::ST_FINISH:

		//Change status
		pItem->itemType = DONWLIST_FINISHED;

		//Close FileHandle
		for(vector<CCURLHelper::TASK_DESCRIPTOR*>::iterator it = m_vecpDownTask.begin(); it != m_vecpDownTask.end(); ++it)
		{
			if((*it)->bIsTaskFinished)
			{
				(*it)->bIsTaskFinished = false;
				::CloseHandle((*it)->hFile);
			}
		}

		//Refresh List Item Status
		SetFocus();
		SelectItem(pItem->uiItemIndex);
		Update(pItem->uiItemIndex);

		break;
	}

	return FALSE;
}

LRESULT CMainDownListView::OnCustomDrawHeader(int idCtrl, LPNMHDR lpnmhdr, BOOL& bHandled)
{

	bHandled = FALSE;
	return CDRF_DODEFAULT;
}

LRESULT CMainDownListView::OnCustomDrawColumn(int idCtrl, LPNMHDR lpnmhdr, BOOL& bHandled)
{
	//We only check msg from self
	if(lpnmhdr->hwndFrom == m_hWnd)
	{
		LPNMLVCUSTOMDRAW pLVCD = (LPNMLVCUSTOMDRAW)lpnmhdr;

		if (CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
		{
			//We want to receive msg for every item
			return CDRF_NOTIFYITEMDRAW;
		}
		else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
		{
			//We want to receive msg for every subitem
			//We have to do this in two stage cause of MSDN
			return CDRF_NOTIFYSUBITEMDRAW;
		}
		else if((CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage)
		{
			//We want to do subitem post paint
			return CDRF_NOTIFYPOSTPAINT;
		}
		else if((CDDS_ITEMPOSTPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage)
		{
			DOWN_LIST_ITEM* pListItem;
			CRect rcRect;
			CDCHandle hdc;
			CDC mdc;
			CBitmapHandle hPreBmp;

			//We'd Like to draw some special columns
			switch(pLVCD->iSubItem)
			{
			case DLST_DOWNSTATUS_COL_INDEX:			//Draw the status icon

				//Get The icon rect and repaint it
				GetSubItemRect(pLVCD->nmcd.dwItemSpec, DLST_DOWNSTATUS_COL_INDEX, LVIR_ICON, &rcRect);

				//Draw the status icon
				hdc.Attach(pLVCD->nmcd.hdc);
				mdc.CreateCompatibleDC();

				//Read item pointer from itemdata
				pListItem = (DOWN_LIST_ITEM*)GetItemData(pLVCD->nmcd.dwItemSpec);
				switch(pListItem->itemType)
				{
				case DOWNLIST_SCHEDULE:
					
					hPreBmp = mdc.SelectBitmap(m_bmpSchedule);
					break;

				case DOWNLIST_SNIFFERING:

					hPreBmp = mdc.SelectBitmap(m_bmpSniffering);
					break;

				case DOWNLIST_READY:

					hPreBmp = mdc.SelectBitmap(m_bmpReady);
					break;

				case DOWNLIST_DOWNLOADING:

					hPreBmp = mdc.SelectBitmap(m_bmpDonwloading);
					break;

				case DWONLIST_PAUSED:
					
					hPreBmp = mdc.SelectBitmap(m_bmpPaused);
					break;

				case DONWLIST_FINISHED:
					
					hPreBmp = mdc.SelectBitmap(m_bmpFinished);
					break;
				}

				hdc.AlphaBlend(rcRect.left, rcRect.top + 1, 16, 16, mdc, 0, 0, 16, 16, alphaBlendFunction);
				mdc.SelectBitmap(hPreBmp);

				break;

			case DLST_FINISHEDPERCENT_COL_INDEX:

				hdc.Attach(pLVCD->nmcd.hdc);
				GetSubItemRect(pLVCD->nmcd.dwItemSpec, DLST_FINISHEDPERCENT_COL_INDEX, LVIR_BOUNDS, &rcRect);

				//Draw a black rectangle
				rcRect.bottom -= 3;
				rcRect.right -= 2;
				rcRect.left += 3;
				rcRect.top += 2;
				hdc.Rectangle(&rcRect);

				//Draw the progress bar, we base all data on item list, not list view
				pListItem = (DOWN_LIST_ITEM*)GetItemData(pLVCD->nmcd.dwItemSpec);

				rcRect.left++;
				rcRect.right--;
				rcRect.top++;
				rcRect.bottom--;

				rcRect.right = rcRect.left + (LONG)((pListItem->fFileMBSize > 0.0f ? pListItem->fFinishedMBSize/pListItem->fFileMBSize : 0.0f) * rcRect.Width());
				hdc.FillSolidRect(&rcRect, DOWNLIST_PROGRESS_COLOR);

				break;
			}
			
			return CDRF_DODEFAULT;
		}

		return CDRF_DODEFAULT;
	}

	//Pass other window's message out
	bHandled = FALSE;
	return FALSE;
}

LRESULT CMainDownListView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	//Show the popup menu
	::TrackPopupMenuEx(m_contMenu.GetSubMenu(0), NULL, LOWORD(lParam), HIWORD(lParam), m_hWnd, NULL);

	return FALSE;
}

LRESULT CMainDownListView::OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	//We Sent it to main window to show info on the status bar
	::PostMessageW(m_hwndMainFrameWindow, uMsg, wParam, lParam);

	//Pass it to default procedure
	bHandled = FALSE;
	return FALSE;
}

LRESULT CMainDownListView::OnDownItemStart(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	MessageBoxW(L"Fuck");

	return TRUE;
}

void CMainDownListView::InitColumnHeader()
{
	WCHAR pwstrTitle[DOWNLOADLIST_COLUMN_MAX_CHAR] = { 0 };

	//Add status column
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_STATUS, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_DOWNSTATUS_COL_INDEX, pwstrTitle, LVCFMT_CENTER, STATUS_COLUMN_INIT_WIDTH);

	//Add FileName column
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_FILENAME, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_FILENAME_COL_INDEX, pwstrTitle, LVCFMT_LEFT, FILENAME_COLUMN_INIT_WIDTH);

	//Add FileSize Column
	::wmemset(pwstrTitle, 0, DOWNLOADLIST_COLUMN_MAX_CHAR);
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_FILESIZE, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_FILESIZE_COL_INDEX, pwstrTitle, LVCFMT_RIGHT, FILESIZE_COLUMN_INIT_WIDTH);

	//Add FinishedSize Column
	::wmemset(pwstrTitle, 0, DOWNLOADLIST_COLUMN_MAX_CHAR);
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_FINISHEDSIZE, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_FINISHEDSIZE_COL_INDEX, pwstrTitle, LVCFMT_RIGHT, FILESIZE_COLUMN_INIT_WIDTH);

	//Add Finished Percent Column
	::wmemset(pwstrTitle, 0, DOWNLOADLIST_COLUMN_MAX_CHAR);
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_FINISHEDPERCENT, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_FINISHEDPERCENT_COL_INDEX, pwstrTitle, LVCFMT_RIGHT, FILESIZE_COLUMN_INIT_WIDTH);

	//Add Lefttime Column
	::wmemset(pwstrTitle, 0, DOWNLOADLIST_COLUMN_MAX_CHAR);
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_LEFTTIME, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_TIMELEFT_COL_INDEX, pwstrTitle, LVCFMT_RIGHT, FILESIZE_COLUMN_INIT_WIDTH);

	//Add Speed Column
	::wmemset(pwstrTitle, 0, DOWNLOADLIST_COLUMN_MAX_CHAR);
	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_DOWNLIST_DOWNSPEED, pwstrTitle, DOWNLOADLIST_COLUMN_MAX_CHAR);
	InsertColumn(DLST_SPEED_COL_INDEX, pwstrTitle, LVCFMT_RIGHT, FILESIZE_COLUMN_INIT_WIDTH);
}

//Redraw the specified type download list
void CMainDownListView::RefreshDownList(DOWN_LIST_TYPE downListType)
{
	UINT uiItemIndex = 0;

	//Delte all existing items
	DeleteAllItems();
	for(list<DOWN_LIST_ITEM>::iterator it = m_lstDownListAll.begin(); it != m_lstDownListAll.end(); ++it, uiItemIndex++)
	{
		//File Status
		AddItem(uiItemIndex, DLST_DOWNSTATUS_COL_INDEX, L"");

		//File Name
		AddItem(uiItemIndex, DLST_FILENAME_COL_INDEX, (*it).wstrFileName.c_str());

		//File MB Size
		WCHAR pwstrFileSizeMB[10] = { 0 };
		::swprintf(pwstrFileSizeMB, 10, L"%.2f M", (*it).fFileMBSize);
		AddItem(uiItemIndex, DLST_FILESIZE_COL_INDEX, pwstrFileSizeMB);

		//File Finished MB Size
		WCHAR pwstrFileFinishedSizeMB[10] = { 0 };
		::swprintf(pwstrFileFinishedSizeMB, 10, L"%.2f M", (*it).fFinishedMBSize);
		AddItem(uiItemIndex, DLST_FINISHEDSIZE_COL_INDEX, pwstrFileFinishedSizeMB);

		//File Finished percentage
		WCHAR pwstrFileFinishedPercent[10] = { 0 };
		::swprintf(pwstrFileFinishedPercent, 10, L"%.2f", (*it).fFinishedMBSize/(*it).fFileMBSize*100.0);
		AddItem(uiItemIndex, DLST_FINISHEDPERCENT_COL_INDEX, pwstrFileFinishedPercent);

		//Set Item Status, we set it the list item's pointer
		SetItemData(uiItemIndex, (DWORD_PTR)&(*it));
	}
}

void CMainDownListView::SnifferScheduledItems()
{
	//Clear the heap if it exist
	ClearPageLinkHeap();

	//We Start a thread to sniffer page link of scheduled list
	//Hold the data on the heap, or the data may be destroyed before the thread started
	for(list<DOWN_LIST_ITEM>::iterator it = m_lstDownListAll.begin(); it != m_lstDownListAll.end(); ++it)
	{
		//We only process scheduled item
		if(it->itemType == DOWNLIST_SCHEDULE)
		{
			CCURLHelper::PAGE_LINK_ITEM* pPageLinkItem = new CCURLHelper::PAGE_LINK_ITEM;
			
			pPageLinkItem->strSecIp = it->strSecIp;
			pPageLinkItem->strURLRefer = it->strURLRefer;
			pPageLinkItem->wstrFileID = it->wstrFileID;
			pPageLinkItem->wstrPostFileName = it->wstrFileName;

			pPageLinkItem->pListItem = (void*)&(*it);

			m_vecPageLinkItem.push_back(pPageLinkItem);
		}
	}

	//If there is items to be sniffer, we start the sniffer thread
	if(m_vecPageLinkItem.size() == 0)
		return;

	//Begin the sniffer thread
	::_beginthread(CCURLHelper::PageLinkSnifferThread, NULL, (void*)&m_vecPageLinkItem);
}

void CMainDownListView::OffSetCurrentListItemIndex(UINT uiOffset)
{
	for(list<DOWN_LIST_ITEM>::iterator it = m_lstDownListAll.begin(); it != m_lstDownListAll.end(); ++it)
	{
		it->uiItemIndex += uiOffset;
	}
}

void CMainDownListView::ClearPageLinkHeap()
{
	//Delete the heap data if the page link heap is not null
	if(m_vecPageLinkItem.size() == 0)
	{
		return;
	}
	else
	{
		for(vector<CCURLHelper::PAGE_LINK_ITEM*>::iterator it = m_vecPageLinkItem.begin(); it != m_vecPageLinkItem.end(); ++it)
		{
			delete *it;
		}
	}

	//We Cleared it
	m_vecPageLinkItem.clear();
}

void CMainDownListView::ShowDownProperty()
{
	//Show PropDown Value
	CDownPropertyDiag diagPropDown(IDS_TA_DOWNPROP_TITLE);

	//Show the Property Page
	diagPropDown.SetLinksData(&m_vecPageLinkItem);
	diagPropDown.DoModal(m_hwndMainFrameWindow);

	//User close the diag, check which page the user choose
	if(diagPropDown.m_pgCurrent == CDownPropertyDiag::PAGE_DOWNPROPERTY)
	{
		//If keep the list as task, we just quit
		if(diagPropDown.m_pageDownProp.m_bIsKeepTask)
		{
			return;
		}

		//Start download, make the task descriptor
		for(vector<CCURLHelper::PAGE_LINK_ITEM*>::iterator it = m_vecPageLinkItem.begin(); it != m_vecPageLinkItem.end(); ++it)
		{
			//We Limit the parellel download
			if((*it)->bIsFoundLink && m_vecpDownTask.size() < m_nMaxParallelDownLoad)
			{
				//Create descript on heap
				CCURLHelper::TASK_DESCRIPTOR* pTask = new CCURLHelper::TASK_DESCRIPTOR;
				DOWN_LIST_ITEM* pItem = (DOWN_LIST_ITEM*)(*it)->pListItem;

				//Make the full path
				WCHAR lpwstrFilePath[MAX_PATH] = { 0 };
				::wcscpy(lpwstrFilePath, diagPropDown.m_pageDownProp.m_wstrSaveFolder.c_str());
				::PathAppend(lpwstrFilePath, (*it)->wstrServerFileName.c_str());

				//Set Task
				pTask->wstrFileFullPath = lpwstrFilePath;
				pTask->sUserSetDownThread = (SHORT)diagPropDown.m_pageDownProp.m_nThread;
				pTask->strDownLoadLink = (*it)->strDownLink;
				pTask->strReferer = (*it)->strURLRefer;
				pTask->pListItem = (*it)->pListItem;

				//Create File
				HANDLE hFile = ::CreateFile(pTask->wstrFileFullPath.c_str(), GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
				pTask->hFile = hFile;

				//Push the heap data to vector, we need it to comunicate with thread
				m_vecpDownTask.push_back(pTask);

				//Start the download Thread
				::_beginthread(CCURLHelper::StartHttpPartDownloadThread, NULL, (void*)pTask);
			}
		}
	}

}

